/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package swym.server.file;

import swym.server.*;
import swym.server.config.*;
import java.io.*;
import java.util.*;

/**
 *
 * @author mschaefer
 */
public class SyncedFile 
{
    private File file;
    private User owner;
    private FileVersion version;
    private String path;
    private int size; // in chunks!
    private HashMap<Integer, FileChunk> dataChunks; // (byte offset, data)
    
    public SyncedFile( User owner, String path, String versionString )
    {
        this.owner = owner;
        this.path = path;
        version = new FileVersion( versionString );
        
        dataChunks = new HashMap<Integer, FileChunk>();
    }
    
    /**
     * Set the size of the file (in chunks!)
     */ 
    public void setSize( int size ) { this.size = size; }
    public int getSize() { return size; }
    
    public void setChunk( FileChunk newChunk )
    {
        synchronized( dataChunks )
        {
            dataChunks.put( newChunk.getOffset(), newChunk );
        }
    }
    
    public Vector<Integer> getChunkOffsets()
    {
        Vector<Integer> keys = null;
        
        synchronized( dataChunks )
        {
             keys = new Vector<Integer>( dataChunks.keySet() );
        }
        
        Collections.sort( keys );
        
        return keys;
    }
    
    public FileChunk getChunk( int byteOffset )
    {
        synchronized( dataChunks )
        {
            return dataChunks.get( byteOffset );
        }
    }
    
    public User getOwner()
    { 
        return owner;
    }
    
    public String getPath()
    {
        return path;
    }
    
    public String getVersion()
    {
        return version.versionString;
    }
    
    public synchronized void writeToDisk() throws IOException 
    {
        BufferedWriter infoFileWriter = null;
        FileOutputStream chunkOutStream = null;
        
        String basePath = FileActionManager.getUserRootPath( owner ) + getLocalPath();
        
        // File
        File infoFile = new File( basePath + ".info" );
        
        synchronized ( dataChunks )
        {
            try
            {
                // First, write the info file which contains the listing of
                // all of the offsets of the data chunks
                infoFileWriter = new BufferedWriter( new FileWriter( infoFile ) );

                Vector<Integer> offsets = getChunkOffsets();

                for ( Integer offset : offsets )
                    infoFileWriter.write( offset.toString() + "\n" );           

                // For each data offset, write out the data to its own
                // offset file.
                // path/file.chunk.OFFSET
                for ( Integer offset: offsets )
                {
                    // creates file: path/filename.chunk.OFFSET
                    File chunkFile = new File( basePath + ".chunk." + offset.toString() );

                    chunkOutStream = new FileOutputStream( chunkFile );

                    byte[] chunkBytes = dataChunks.get( offset ).getData();

                    chunkOutStream.write( chunkBytes );

                    chunkOutStream.close();
                }   
            }
            finally
            {
                if ( infoFileWriter != null )
                    infoFileWriter.close();

                if ( chunkOutStream != null )
                    chunkOutStream.close();
            }
        } // end synchronized( dataChunks )
                
    }
    
    private String getLocalPath( )
    {
        return path.replace( ":", File.separator ) + "." + version;
    }
    
    public String toString()
    {
        return owner.getName() + ":" + path + ":" + version;
    }
            
    private class FileVersion // implements Comparable<FileVersion>
    {
        private String versionString;
        private String version;
        private String client;
        
        public FileVersion( String versionString )
        {
           this.versionString = versionString; 
           
           String[] portions = versionString.split( "-" );
           
           if ( portions.length == 2 )
           {
                client = portions[0];
                version = portions[1];
           }
           // TODO: what if not there?!
        }
                   
        public String toString()
        {
           return versionString;
        }
    }
}
